home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / sp_lev.c < prev    next >
C/C++ Source or Header  |  1993-01-14  |  59KB  |  2,478 lines

  1. /*    SCCS Id: @(#)sp_lev.c    3.1    92/11/14    */
  2. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the various functions that are related to the special
  7.  * levels.
  8.  * It contains also the special level loader.
  9.  *
  10.  */
  11.  
  12. #include "hack.h"
  13. /*#define DEBUG     /* uncomment to enable code debugging */
  14.  
  15. #ifdef DEBUG
  16. # ifdef WIZARD
  17. #define debugpline    if (wizard) pline
  18. # else
  19. #define debugpline    pline
  20. # endif
  21. #endif
  22.  
  23. #include "sp_lev.h"
  24. #include "rect.h"
  25.  
  26. extern void FDECL(mkmap, (lev_init *));
  27.  
  28. static void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
  29. static void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *));
  30. static void FDECL(create_trap, (trap *, struct mkroom *));
  31. static void FDECL(create_monster, (monster *, struct mkroom *));
  32. static void FDECL(create_object, (object *, struct mkroom *));
  33. static void FDECL(create_stairs, (stair *, struct mkroom *));
  34. static void FDECL(create_altar, (altar *, struct mkroom *));
  35. static void FDECL(create_gold, (gold *, struct mkroom *));
  36. static void FDECL(create_feature, (int,int,struct mkroom *,int));
  37. static boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *,
  38.                     XCHAR_P, int));
  39. static void NDECL(fix_stair_rooms);
  40. static void FDECL(create_corridor, (corridor *));
  41.  
  42. static boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
  43.                     XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
  44.  
  45. #if defined(MICRO) && !defined(AMIGA)
  46. # define RDMODE "rb"
  47. #else
  48. # define RDMODE "r"
  49. #endif
  50.  
  51. #define LEFT    1
  52. #define H_LEFT    2
  53. #define CENTER    3
  54. #define H_RIGHT    4
  55. #define RIGHT    5
  56.  
  57. #define TOP    1
  58. #define BOTTOM    5
  59.  
  60. #define sq(x) ((x)*(x))
  61.  
  62. #define XLIM    4
  63. #define YLIM    3
  64.  
  65. #define Fread    (void)fread
  66. #define New(type)        (type *) alloc(sizeof(type))
  67. #define NewTab(type, size)    (type **) alloc(sizeof(type *) * size)
  68. #define Free(ptr)        if(ptr) free((genericptr_t) (ptr))
  69.  
  70. static walk NEARDATA walklist[50];
  71. extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
  72.  
  73. static char Map[COLNO][ROWNO];
  74. static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10];
  75. static aligntyp    ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
  76. static xchar NEARDATA xstart, NEARDATA ystart;
  77. static char NEARDATA xsize, NEARDATA ysize;
  78.  
  79. static void FDECL(make_walls_nondiggable, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
  80. static int NDECL(rnddoor);
  81. static int NDECL(rndtrap);
  82. static void FDECL(get_location, (schar *,schar *,int));
  83. static void FDECL(sp_lev_shuffle, (char *,char *,int));
  84. static void FDECL(light_region, (region *));
  85. static void FDECL(load_common_data, (FILE *,int));
  86. static boolean FDECL(load_rooms, (FILE *));
  87. static void FDECL(maze1xy, (coord *));
  88. static boolean FDECL(load_maze, (FILE *));
  89. static void FDECL(create_door, (room_door *, struct mkroom *));
  90. static void FDECL(free_rooms,(room **, int));
  91. static void FDECL(build_room, (room *, room*));
  92.  
  93. char *lev_message = 0;
  94. lev_region *lregions = 0;
  95. int num_lregions = 0;
  96. lev_init init_lev;
  97.  
  98. /*
  99.  * Make walls of the area (x1, y1, x2, y2) non diggable
  100.  */
  101.  
  102. static void
  103. make_walls_nondiggable(x1,y1,x2,y2)
  104. xchar x1, y1, x2, y2;
  105. {
  106.     register xchar x, y;
  107.  
  108.     for(y = y1; y <= y2; y++)
  109.         for(x = x1; x <= x2; x++)
  110.         if(IS_STWALL(levl[x][y].typ))
  111.             levl[x][y].diggable |= W_NONDIGGABLE;
  112. }
  113.  
  114. /*
  115.  * Choose randomly the state (nodoor, open, closed or locked) for a door
  116.  */
  117.  
  118. static int
  119. rnddoor()
  120. {
  121.     int i;
  122.     
  123.     i = 1 << rn2(5);
  124.     i >>= 1;
  125.     return i;
  126. }
  127.  
  128. /* 
  129.  * Select a random trap
  130.  */
  131.  
  132. static int
  133. rndtrap()
  134. {
  135.     int    rtrap, no_tdoor = !Can_dig_down(&u.uz);
  136.     do {
  137.         rtrap = rnd(TRAPNUM-1);
  138.     } while (rtrap == MAGIC_PORTAL || (no_tdoor && rtrap == TRAPDOOR));
  139.     return(rtrap);
  140. }
  141.  
  142. /* 
  143.  * Coordinates in special level files are handled specially:
  144.  *
  145.  *    if x or y is -11, we generate a random coordinate.
  146.  *    if x or y is between -1 and -10, we read one from the corresponding
  147.  *    register (x0, x1, ... x9).
  148.  *    if x or y is nonnegative, we convert it from relative to the local map
  149.  *    to global coordinates.
  150.  *    The "humidity" flag is used to insure that engravings aren't
  151.  *    created underwater, or eels on dry land.
  152.  */
  153. #define DRY    0x1
  154. #define WET    0x2
  155.  
  156. static boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
  157.  
  158. static void
  159. get_location(x, y, humidity)
  160. schar *x, *y;
  161. int humidity;
  162. {
  163.     int cpt = 0;
  164.  
  165.     if (*x >= 0) {            /* normal locations */
  166.         *x += xstart;
  167.         *y += ystart;
  168.     } else if (*x > -11) {        /* special locations */
  169.         *y = ystart + rloc_y[ - *y - 1];
  170.         *x = xstart + rloc_x[ - *x - 1];
  171.     } else {            /* random location */
  172.         do {
  173.         *x = xstart + rn2((int)xsize);
  174.         *y = ystart + rn2((int)ysize);
  175.         if (is_ok_location(*x,*y,humidity)) break;
  176.         } while (++cpt < 100);
  177.         if (cpt >= 100) {
  178.         register int xx, yy;
  179.         /* last try */
  180.         for (xx = 0; xx < xsize; xx++)
  181.             for (yy = 0; yy < ysize; yy++) {
  182.             *x = xstart + xx;
  183.             *y = ystart + yy;
  184.             if (is_ok_location(*x,*y,humidity)) goto found_it;
  185.             }
  186.         panic("get_location:  can't find a place!");
  187.         }
  188.     }
  189. found_it:;
  190.  
  191.     if (*x <= 0 || *x >= COLNO || *y < 0 || *y >= ROWNO) {
  192.         impossible("get_location:  (%d,%d) out of bounds", *x, *y);
  193.         *x = x_maze_max; *y = y_maze_max;
  194.     }
  195. }
  196.  
  197. static boolean
  198. is_ok_location(x, y, humidity)
  199. register schar x, y;
  200. register int humidity;
  201. {
  202.     register int typ;
  203.     register boolean okplace = FALSE;
  204.  
  205.     if (humidity & DRY) {
  206.         typ = levl[x][y].typ;
  207.         okplace = (typ == ROOM || typ == AIR ||
  208.             typ == CLOUD || typ == CORR);
  209.     }
  210.     if (humidity & WET) {
  211.         if (is_pool(x,y) || is_lava(x,y))
  212.         okplace = TRUE;
  213.     }
  214.     return okplace;
  215. }
  216.  
  217. /*
  218.  * Shuffle the registers for locations, objects or monsters
  219.  */
  220.  
  221. static void
  222. sp_lev_shuffle(list1, list2, n)
  223. char list1[], list2[];
  224. int n;
  225. {
  226.     register int i, j;
  227.     register char k;
  228.  
  229.     for (i = n - 1; i > 0; i--) {
  230.         if ((j = rn2(i + 1)) == i) continue;
  231.         k = list1[j];
  232.         list1[j] = list1[i];
  233.         list1[i] = k;
  234.         if (list2) {
  235.             k = list2[j];
  236.             list2[j] = list2[i];
  237.             list2[i] = k;
  238.         }
  239.     }
  240. }
  241.  
  242. /* 
  243.  * Get a relative position inside a room.
  244.  * negative values for x or y means RANDOM!
  245.  */
  246.  
  247. static void
  248. get_room_loc(x,y, croom)
  249. schar        *x, *y;
  250. struct mkroom    *croom;
  251. {
  252.     coord c;
  253.  
  254.     if (*x <0 && *y <0) {
  255.         if (somexy(croom, &c)) {
  256.             *x = c.x;
  257.             *y = c.y;
  258.         } else
  259.             panic("get_room_loc : can't find a place!");
  260.     } else {
  261.         if (*x < 0)
  262.             *x = rn2(croom->hx - croom->lx + 1);
  263.         if (*y < 0)
  264.             *y = rn2(croom->hy - croom->ly + 1);
  265.         *x += croom->lx;
  266.         *y += croom->ly;
  267.     }
  268. }
  269.  
  270. /* 
  271.  * Get a relative position inside a room.
  272.  * negative values for x or y means RANDOM!
  273.  */
  274.  
  275. static void
  276. get_free_room_loc(x,y, croom)
  277. schar        *x, *y;
  278. struct mkroom    *croom;
  279. {
  280.     schar try_x, try_y;
  281.     register int trycnt = 0;
  282.  
  283.     do {
  284.         try_x = *x,  try_y = *y;
  285.         get_room_loc(&try_x, &try_y, croom);
  286.     } while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
  287.  
  288.     if (trycnt > 100)
  289.         panic("get_free_room_loc:  can't find a place!");
  290.     *x = try_x,  *y = try_y;
  291. }
  292.  
  293. boolean
  294. check_room(lowx, ddx, lowy, ddy, vault)
  295. xchar *lowx, *ddx, *lowy, *ddy;
  296. boolean vault;
  297. {
  298.     register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy;
  299.     register struct rm *lev;
  300.     int xlim, ylim, ymax;
  301.  
  302.     xlim = XLIM + (vault ? 1 : 0);
  303.     ylim = YLIM + (vault ? 1 : 0);
  304.     
  305.     if (*lowx < 3)        *lowx = 3;
  306.     if (*lowy < 2)        *lowy = 2;
  307.     if (hix > COLNO-3)    hix = COLNO-3;
  308.     if (hiy > ROWNO-3)    hiy = ROWNO-3;
  309. chk:
  310.     if (hix <= *lowx || hiy <= *lowy)    return FALSE;
  311.  
  312.     /* check area around room (and make room smaller if necessary) */
  313.     for (x = *lowx - xlim; x<= hix + xlim; x++) {
  314.         if(x <= 0 || x >= COLNO) continue;
  315.         y = *lowy - ylim;    ymax = hiy + ylim;
  316.         if(y < 0) y = 0;
  317.         if(ymax >= ROWNO) ymax = (ROWNO-1);
  318.         lev = &levl[x][y];
  319.         for (; y <= ymax; y++) {
  320.             if (lev++->typ) {
  321. #ifdef DEBUG
  322.                 if(!vault)
  323.                     debugpline("strange area [%d,%d] in check_room.",x,y);
  324. #endif
  325.                 if (!rn2(3))    return FALSE;
  326.                 if (x < *lowx)
  327.                     *lowx = x + xlim + 1;
  328.                 else
  329.                     hix = x - xlim - 1;
  330.                 if (y < *lowy)
  331.                     *lowy = y + ylim + 1;
  332.                 else
  333.                     hiy = y - ylim - 1;
  334.                 goto chk;
  335.             }
  336.         }
  337.     }
  338.     *ddx = hix - *lowx;
  339.     *ddy = hiy - *lowy;
  340.     return TRUE;
  341. }
  342.  
  343. /* 
  344.  * Create a new room.
  345.  * This is still very incomplete...
  346.  */
  347.  
  348. boolean
  349. create_room(x,y,w,h,xal,yal,rtype,rlit)
  350. xchar    x,y;
  351. xchar    w,h;
  352. xchar    xal,yal;
  353. xchar    rtype, rlit;
  354. {
  355.     xchar    xabs, yabs;
  356.     int    wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
  357.     NhRect    *r1 = 0, r2;
  358.     int    trycnt = 0;
  359.     boolean    vault = FALSE;
  360.     int    xlim = XLIM, ylim = YLIM;
  361.  
  362.     if (rtype == -1)    /* Is the type random ? */
  363.         rtype = OROOM;
  364.  
  365.     if (rtype == VAULT) {
  366.         vault = TRUE;
  367.         xlim++;
  368.         ylim++;
  369.     }
  370.  
  371.     /* on low levels the room is lit (usually) */
  372.     /* some other rooms may require lighting */
  373.  
  374.     /* is light state random ? */
  375.     if (rlit == -1)
  376.         rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  377.  
  378.     /*
  379.      * Here we will try to create a room. If some parameters are
  380.      * random we are willing to make several try before we give
  381.      * it up.
  382.      */
  383.     do {
  384.         xchar xborder, yborder;
  385.         wtmp = w; htmp = h;
  386.         xtmp = x; ytmp = y;
  387.         xaltmp = xal; yaltmp = yal;
  388.  
  389.         /* First case : a totaly random room */
  390.  
  391.         if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 &&
  392.            yaltmp < 0) || vault) {
  393.             xchar hx, hy, lx, ly, dx, dy;
  394.             r1 = rnd_rect(); /* Get a random rectangle */
  395.  
  396.             if (!r1) { /* No more free rectangles ! */
  397. #ifdef DEBUG
  398.                 debugpline("No more rects...");
  399. #endif
  400.                 return FALSE;
  401.             }
  402.             hx = r1->hx;
  403.             hy = r1->hy;
  404.             lx = r1->lx;
  405.             ly = r1->ly;
  406.             if (vault)
  407.                 dx = dy = 1;
  408.             else {
  409.                 dx = 2 + rn2((hx-lx > 28) ? 12 : 8);
  410.                 dy = 2 + rn2(4);
  411.                 if(dx*dy > 50)
  412.                     dy = 50/dx;
  413.             }
  414.             xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1;
  415.             yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1;
  416.             if(hx-lx < dx + 3 + xborder ||
  417.                hy-ly < dy + 3 + yborder) {
  418.                 r1 = 0;
  419.                 continue;
  420.             }
  421.             xabs = lx + (lx > 0 ? xlim : 3)
  422.                 + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1);
  423.             yabs = ly + (ly > 0 ? ylim : 2) 
  424.                 + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1);
  425.             if (ly == 0 && hy >= (ROWNO-1) &&
  426.                 (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) {
  427.                 yabs = rn1(3, 2);
  428.                 if(nroom < 4 && dy>1) dy--;
  429.                 }
  430.             if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
  431.                 r1 = 0;
  432.                 continue;
  433.             }
  434.             wtmp = dx+1;
  435.             htmp = dy+1;
  436.             r2.lx = xabs-1; r2.ly = yabs-1;
  437.             r2.hx = xabs + wtmp;
  438.             r2.hy = yabs + htmp;
  439.         } else {    /* Only some parameters are random */
  440.             int rndpos = 0;
  441.             if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
  442.                 xtmp = rnd(5);
  443.                 ytmp = rnd(5);
  444.                 rndpos = 1;
  445.             }
  446.             if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
  447.                 wtmp = rn1(15, 3);
  448.                 htmp = rn1(8, 2);
  449.             }
  450.             if (xaltmp == -1) /* Horizontal alignment is RANDOM */
  451.                 xaltmp = rnd(3);
  452.             if (yaltmp == -1) /* Vertical alignment is RANDOM */
  453.                 yaltmp = rnd(3);
  454.  
  455.             /* Try to generate real (absolute) coordinates here! */
  456.             
  457.             xabs = (((xtmp-1) * COLNO) / 5) + 1;
  458.             yabs = (((ytmp-1) * ROWNO) / 5) + 1;
  459.             switch (xaltmp) {
  460.                   case LEFT:
  461.                 break;
  462.                   case RIGHT:
  463.                 xabs += (COLNO / 5) - wtmp;
  464.                 break;
  465.                   case CENTER:
  466.                 xabs += ((COLNO / 5) - wtmp) / 2;
  467.                 break;
  468.             }
  469.             switch (yaltmp) {
  470.                   case TOP:
  471.                 break;
  472.                   case BOTTOM:
  473.                 yabs += (ROWNO / 5) - htmp;
  474.                 break;
  475.                   case CENTER:
  476.                 yabs += ((ROWNO / 5) - htmp) / 2;
  477.                 break;
  478.             }
  479.             
  480.             if (xabs + wtmp - 1 > COLNO - 2) 
  481.                 xabs = COLNO - wtmp - 3;
  482.             
  483.             if (xabs < 2)
  484.                 xabs = 2;
  485.             
  486.             if (yabs + htmp - 1> ROWNO - 2)
  487.                 yabs = ROWNO - htmp - 3;
  488.  
  489.             if (yabs < 2)
  490.                 yabs = 2;
  491.             /* Try to find a rectangle that fit our room ! */
  492.  
  493.             r2.lx = xabs-1; r2.ly = yabs-1;
  494.             r2.hx = xabs + wtmp + rndpos;
  495.             r2.hy = yabs + htmp + rndpos;
  496.             r1 = get_rect(&r2);
  497.         }
  498.     } while (++trycnt <= 100 && !r1);
  499.     if (!r1) {    /* creation of room failed ? */
  500.         return FALSE;
  501.     }
  502.     split_rects(r1, &r2);
  503.  
  504.     if (!vault) {
  505.         smeq[nroom] = nroom;
  506.         add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,
  507.              rlit, rtype, FALSE);
  508.     } else {
  509.         rooms[nroom].lx = xabs;
  510.         rooms[nroom].ly = yabs;
  511.     }
  512.     return TRUE;
  513. }
  514.  
  515. /* 
  516.  * Create a subroom in room proom at pos x,y with width w & height h.
  517.  * x & y are relative to the parent room.
  518.  */
  519.  
  520. static boolean
  521. create_subroom(proom, x, y, w,  h, rtype, rlit)
  522. struct mkroom *proom;
  523. xchar x,y;
  524. xchar w,h;
  525. xchar rtype, rlit;
  526. {
  527.     xchar width, height;
  528.  
  529.     width = proom->hx - proom->lx + 1;
  530.     height = proom->hy - proom->ly + 1;
  531.  
  532.     /* There is a minimum size for the parent room */
  533.     if (width < 4 || height < 4)
  534.         return FALSE;
  535.  
  536.     /* Check for random position, size, etc... */
  537.  
  538.     if (w == -1)
  539.         w = rnd(width - 3);
  540.     if (h == -1)
  541.         h = rnd(height - 3);
  542.     if (x == -1)
  543.         x = rnd(width - w - 1) - 1;
  544.     if (y == -1)
  545.         y = rnd(height - h - 1) - 1;
  546.     if (x == 1)
  547.         x = 0;
  548.     if (y == 1)
  549.         y = 0;
  550.     if ((x + w + 1) == width)
  551.         x++;
  552.     if ((y + h + 1) == height)
  553.         y++;
  554.     if (rtype == -1)
  555.         rtype = OROOM;
  556.     if (rlit == -1)
  557.         rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  558.     add_subroom(proom, proom->lx + x, proom->ly + y, 
  559.             proom->lx + x + w - 1, proom->ly + y + h - 1,
  560.             rlit, rtype, FALSE);
  561.     return TRUE;
  562. }
  563.  
  564. /* 
  565.  * Create a new door in a room.
  566.  * It's placed on a wall (north, south, east or west).
  567.  */
  568.  
  569. static void
  570. create_door(dd, broom)
  571. room_door *dd;
  572. struct mkroom *broom;
  573. {
  574.     int    x, y;
  575.     int    trycnt = 0;
  576.  
  577.     if (dd->secret == -1)
  578.         dd->secret = rn2(2);
  579.  
  580.     if (dd->mask == -1) {
  581.         /* is it a locked door, closed, or a doorway? */
  582.         if (!dd->secret) {
  583.             if(!rn2(3)) {
  584.                 if(!rn2(5))
  585.                     dd->mask = D_ISOPEN;
  586.                 else if(!rn2(6))
  587.                     dd->mask = D_LOCKED;
  588.                 else
  589.                     dd->mask = D_CLOSED;
  590.                 if (dd->mask != D_ISOPEN && !rn2(25))
  591.                     dd->mask |= D_TRAPPED;
  592.             } else 
  593.                 dd->mask = D_NODOOR;
  594.         } else {
  595.             if(!rn2(5))    dd->mask = D_LOCKED;
  596.             else        dd->mask = D_CLOSED;
  597.  
  598.             if(!rn2(20)) dd->mask |= D_TRAPPED;
  599.         }
  600.     }
  601.  
  602.     do {
  603.         register int dwall, dpos;
  604.  
  605.         dwall = dd->wall;
  606.         if (dwall == -1)    /* The wall is RANDOM */
  607.             dwall = 1 << rn2(4);
  608.  
  609.         dpos = dd->pos;
  610.         if (dpos == -1)    /* The position is RANDOM */
  611.             dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
  612.                 (broom->hy - broom->ly) : (broom->hx - broom->lx));
  613.         
  614.         /* Convert wall and pos into an absolute coordinate! */
  615.         
  616.         switch (dwall) {
  617.               case W_NORTH:
  618.             y = broom->ly - 1;
  619.             x = broom->lx + dpos;
  620.             break;
  621.               case W_SOUTH:
  622.             y = broom->hy + 1;
  623.             x = broom->lx + dpos;
  624.             break;
  625.               case W_WEST:
  626.             x = broom->lx - 1;
  627.             y = broom->ly + dpos;
  628.             break;
  629.               case W_EAST:
  630.             x = broom->hx + 1;
  631.             y = broom->ly + dpos;
  632.             break;
  633.               default:
  634.             x = y = 0;
  635.             panic("create_door: No wall for door!");
  636.             break;
  637.         }
  638.         if (okdoor(x,y))
  639.             break;
  640.     } while (++trycnt <= 100);
  641.     if (trycnt > 100) {
  642.         impossible("create_door: Can't find a proper place!");
  643.         return;
  644.     }
  645.     add_door(x,y,broom);
  646.     levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
  647.     levl[x][y].doormask = dd->mask;
  648. }
  649.  
  650. /*
  651.  * Create a secret door in croom on any one of the specified walls.
  652.  */
  653. void
  654. create_secret_door(croom, walls)
  655.     struct mkroom *croom;
  656.     xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
  657. {
  658.     xchar sx, sy; /* location of the secret door */
  659.     int count;
  660.  
  661.     for(count = 0; count < 100; count++) {
  662.     sx = rn1(croom->hx - croom->lx + 1, croom->lx);
  663.     sy = rn1(croom->hy - croom->ly + 1, croom->ly);
  664.  
  665.     switch(rn2(4)) {
  666.     case 0:  /* top */
  667.         if(!(walls & W_NORTH)) continue;
  668.         sy = croom->ly-1; break;
  669.     case 1: /* bottom */
  670.         if(!(walls & W_SOUTH)) continue;
  671.         sy = croom->hy+1; break;
  672.     case 2: /* left */
  673.         if(!(walls & W_EAST)) continue;
  674.         sx = croom->lx-1; break;
  675.     case 3: /* right */
  676.         if(!(walls & W_WEST)) continue;
  677.         sx = croom->hx+1; break;
  678.     }
  679.  
  680.     if(okdoor(sx,sy)) {
  681.         levl[sx][sy].typ = SDOOR;
  682.         levl[sx][sy].doormask = D_CLOSED;
  683.         add_door(sx,sy,croom);
  684.         return;
  685.     }
  686.     }
  687.  
  688.     impossible("couldn't create secret door on any walls 0x%x", walls);
  689. }
  690.  
  691. /* 
  692.  * Create a trap in a room.
  693.  */
  694.  
  695. static void
  696. create_trap(t,croom)
  697. trap    *t;
  698. struct mkroom    *croom;
  699. {
  700.     schar        x,y;
  701.     coord tm;
  702.  
  703.     x = t->x;
  704.     y = t->y;
  705.     if (croom)
  706.         get_free_room_loc(&x, &y, croom);
  707.     else
  708.         get_location(&x, &y, DRY);
  709.  
  710.     tm.x = x;
  711.     tm.y = y;
  712.  
  713.     mktrap(t->type, 1, (struct mkroom*) 0, &tm);
  714. }
  715.  
  716. /* 
  717.  * Create a monster in a room.
  718.  */
  719.  
  720. static void
  721. create_monster(m,croom)
  722. monster    *m;
  723. struct mkroom    *croom;
  724. {
  725.     struct monst    *mtmp;
  726.     schar        x,y;
  727.     char        class;
  728.     aligntyp    amask;
  729.     struct permonst *pm;
  730.  
  731.     if (m->class >= 0) {
  732.         class = (char) def_char_to_monclass((char)m->class);
  733.         if (class == MAXMCLASSES) goto bad_class;
  734.     } else if (m->class > -11) {
  735.         class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
  736.         if (class == MAXMCLASSES) {
  737. bad_class:
  738.         panic("create_monster: unknown monster class '%c'", m->class);
  739.         }
  740.     } else
  741.         class = 0;
  742.  
  743.     amask = (m->align <= -11) ? induced_align(80) :
  744.         (m->align < 0 ? ralign[-m->align-1] : m->align);
  745.  
  746.     if (!class)
  747.         pm = (struct permonst *) 0;
  748.     else if (m->id != -1) {
  749. #ifdef MULDGN
  750.         if(pl_character[0] == 'E' && m->id == PM_EARENDIL)
  751.         m->id += flags.female;
  752. #endif
  753.         pm = &mons[m->id];
  754.     } else {
  755.         pm = mkclass(class,G_NOGEN);
  756.         /* if we can't get class for a specific monster type,
  757.            it means, that it's extinct, genocided, or unique,
  758.            and shouldn't be created. */
  759.         if (!pm) return;
  760.     }
  761.  
  762.     x = m->x;
  763.     y = m->y;
  764.     if (croom)
  765.         get_room_loc(&x, &y, croom);
  766.     else {
  767.         if (!pm || !is_swimmer(pm))
  768.         get_location(&x, &y, DRY);
  769.         else if (pm->mlet == S_EEL)
  770.         get_location(&x, &y, WET);
  771.         else
  772.         get_location(&x, &y, DRY|WET);
  773.     }
  774.  
  775.  
  776.     if(m->align != -12)
  777.         mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
  778.     else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
  779.              mtmp = mk_mplayer(pm, x, y, FALSE);
  780.     else mtmp = makemon(pm, x, y);
  781.  
  782.     if (mtmp) {
  783.         /* handle specific attributes for some special monsters */
  784.         if (m->name) mtmp = christen_monst(mtmp, m->name);
  785.  
  786.         /*
  787.          * This is currently hardwired for mimics only.  It should
  788.          * eventually be expanded.
  789.          */
  790.         if (m->appear_as && mtmp->data->mlet == S_MIMIC) {
  791.         int i;
  792.  
  793.         switch (m->appear) {
  794.             case M_AP_NOTHING:
  795.             impossible(
  796.         "create_monster: mon has an appearance, \"%s\", but no type",
  797.                 m->appear_as);
  798.             break;
  799.  
  800.             case M_AP_FURNITURE:
  801.             for (i = 0; i < MAXPCHARS; i++)
  802.                 if (!strcmp(defsyms[i].explanation, m->appear_as))
  803.                 break;
  804.             if (i == MAXPCHARS) {
  805.                 impossible(
  806.                 "create_monster: can't find feature \"%s\"",
  807.                     m->appear_as);
  808.             } else {
  809.                 mtmp->m_ap_type = M_AP_FURNITURE;
  810.                 mtmp->mappearance = i;
  811.             }
  812.             break;
  813.  
  814.             case M_AP_OBJECT:
  815.             for (i = 0; i < NROFOBJECTS; i++)
  816.                 if (!strcmp(OBJ_NAME(objects[i]), m->appear_as))
  817.                 break;
  818.             if (i == NROFOBJECTS) {
  819.                 impossible(
  820.                 "create_monster: can't find object \"%s\"",
  821.                     m->appear_as);
  822.             } else {
  823.                 mtmp->m_ap_type = M_AP_OBJECT;
  824.                 mtmp->mappearance = i;
  825.             }
  826.             break;
  827.  
  828.             case M_AP_MONSTER:
  829.             /* note: mimics don't appear as monsters! */
  830.             /*      (but chameleons can :-)      */
  831.             default:
  832.             impossible(
  833.         "create_monster: unimplemented mon appear type [%d,\"%s\"]",
  834.                 m->appear, m->appear_as);
  835.             break;
  836.         }
  837.         if (does_block(x, y, &levl[x][y]))
  838.             block_point(x, y);
  839.         }
  840.  
  841.         if (m->peaceful >= 0) {
  842.         mtmp->mpeaceful = m->peaceful;
  843.         /* changed mpeaceful again; have to reset malign */
  844.         set_malign(mtmp);
  845.         }
  846.         if (m->asleep >= 0) mtmp->msleep = m->asleep;
  847.     }
  848. }
  849.  
  850. /* 
  851.  * Create an object in a room.
  852.  */
  853.  
  854. static void
  855. create_object(o,croom)
  856. object    *o;
  857. struct mkroom    *croom;
  858. {
  859.     struct obj    *otmp;
  860.     schar    x,y;
  861.     char    c;
  862.  
  863.     x = o->x; y = o->y;
  864.     if (croom)
  865.         get_room_loc(&x, &y, croom);
  866.     else
  867.         get_location(&x, &y, DRY);
  868.  
  869.     if (o->class >= 0)
  870.         c = o->class;
  871.     else if (o->class > -11)
  872.         c = robjects[ -(o->class+1)];
  873.     else
  874.         c = 0;
  875.  
  876.     if (!c)
  877.         otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
  878.     else if (o->id != -1)
  879.         otmp = mksobj_at(o->id, x, y, TRUE);
  880.     else {
  881.         /*
  882.          * The special levels are compiled with the default "text" object
  883.          * class characters.  We must convert them to the internal format.
  884.          */
  885.         char oclass = (char) def_char_to_objclass(c);
  886.  
  887.         if (oclass == MAXOCLASSES)
  888.         panic("create_object:  unexpected object class '%c'",c);
  889.         otmp = mkobj_at(oclass, x, y, TRUE);
  890.     }
  891.  
  892.     if (o->spe != -127)    /* That means NOT RANDOM! */
  893.         otmp->spe = o->spe;
  894.  
  895.     switch (o->curse_state) {
  896.           case 1:    bless(otmp); break; /* BLESSED */
  897.           case 2:    unbless(otmp); uncurse(otmp); break; /* uncursed */
  898.           case 3:    curse(otmp); break; /* CURSED */
  899.           default:    break;    /* Otherwise it's random and we're happy
  900.                  * with what mkobj gave us! */
  901.     }
  902.  
  903.     /*     corpsenm is "empty" if -1, random if -2, otherwise specific */
  904.     if (o->corpsenm == -2) otmp->corpsenm = rndmonnum();
  905.     else if (o->corpsenm != -1) otmp->corpsenm = o->corpsenm;
  906.  
  907.     if (o->name) {        /* Give a name to that object */
  908.         /* Note: oname() is safe since otmp is first in chains */
  909.         otmp = oname(otmp, o->name, 0);
  910.         fobj = otmp;
  911.         level.objects[x][y] = otmp;
  912.     }
  913.     stackobj(otmp);
  914. }
  915.  
  916. /* 
  917.  * Create stairs in a room.
  918.  * 
  919.  */
  920.  
  921. static void
  922. create_stairs(s,croom)
  923. stair    *s;
  924. struct mkroom    *croom;
  925. {
  926.     schar        x,y;
  927.  
  928.     x = s->x; y = s->y;
  929.     get_free_room_loc(&x, &y, croom);
  930.     mkstairs(x,y,(char)s->up, croom);
  931. }
  932.  
  933. /* 
  934.  * Create an altar in a room.
  935.  */
  936.  
  937. static void
  938. create_altar(a, croom)
  939.     altar        *a;
  940.     struct mkroom    *croom;
  941. {
  942.     schar        sproom,x,y;
  943.     aligntyp    amask;
  944.     boolean        croom_is_temple = TRUE;
  945.  
  946.     x = a->x; y = a->y;
  947.  
  948.     if (croom) {
  949.         get_free_room_loc(&x, &y, croom);
  950.         if (croom->rtype != TEMPLE)
  951.         croom_is_temple = FALSE;
  952.     } else {
  953.         get_location(&x, &y, DRY);
  954.         if (sproom = (schar) *in_rooms(x, y, TEMPLE))
  955.         croom = &rooms[sproom - ROOMOFFSET];
  956.         else
  957.         croom_is_temple = FALSE;
  958.     }
  959.  
  960.     a->x = x;
  961.     a->y = y;
  962.  
  963.     /* Is the alignment random ?
  964.      * If so, it's an 80% chance that the altar will be co-aligned.
  965.      *
  966.      * The alignment is encoded as amask values instead of alignment
  967.      * values to avoid conflicting with the rest of the encoding,
  968.      * shared by many other parts of the special level code.
  969.      */
  970.  
  971.     amask = (a->align == -11) ? induced_align(80) :
  972.         (a->align < 0 ? ralign[-a->align-1] : a->align);
  973.  
  974.     levl[x][y].typ = ALTAR;
  975.     levl[x][y].altarmask = amask;
  976.  
  977.     if (a->shrine == -11) a->shrine = rn2(1);  /* handle random case */
  978.  
  979.     if (!croom_is_temple || !a->shrine) return;
  980.  
  981.     if (a->shrine) {    /* Is it a shrine  or sanctum? */
  982.         priestini(&u.uz, croom, x, y, (a->shrine > 1));
  983.         levl[x][y].altarmask |= AM_SHRINE;
  984.         level.flags.has_temple = TRUE;
  985.     }
  986. }
  987.  
  988. /* 
  989.  * Create a gold pile in a room.
  990.  */
  991.  
  992. static void
  993. create_gold(g,croom)
  994. gold *g;
  995. struct mkroom    *croom;
  996. {
  997.     schar        x,y;
  998.  
  999.     x = g->x; y= g->y;
  1000.     if (croom)
  1001.         get_room_loc(&x, &y, croom);
  1002.     else
  1003.         get_location(&x, &y, DRY);
  1004.  
  1005.     if (g->amount == -1)
  1006.         g->amount = rnd(200);
  1007.     mkgold((long) g->amount, x, y);
  1008. }
  1009.  
  1010. /* 
  1011.  * Create a feature (e.g a fountain) in a room.
  1012.  */
  1013.  
  1014. static void
  1015. create_feature(fx, fy, croom, typ)
  1016. int        fx, fy;
  1017. struct mkroom    *croom;
  1018. int        typ;
  1019. {
  1020.     schar        x,y;
  1021.     int        trycnt = 0;
  1022.  
  1023.     x = fx;  y = fy;
  1024.     if (croom) {
  1025.         if (x < 0 && y < 0)
  1026.         do {
  1027.             x = -1;  y = -1;
  1028.             get_room_loc(&x, &y, croom);
  1029.         } while (++trycnt <= 200 && occupied(x,y));
  1030.         else
  1031.         get_room_loc(&x, &y, croom);
  1032.         if(trycnt > 200)
  1033.         return;
  1034.     } else {
  1035.         get_location(&x, &y, DRY);
  1036.     }
  1037.     levl[x][y].typ = typ;
  1038. }
  1039.  
  1040. /* 
  1041.  * Search for a door in a room on a specified wall.
  1042.  */
  1043.  
  1044. static boolean
  1045. search_door(croom,x,y,wall,cnt)
  1046. struct mkroom *croom;
  1047. xchar *x, *y;
  1048. xchar wall;
  1049. int cnt;
  1050. {
  1051.     int dx, dy;
  1052.     int xx,yy;
  1053.  
  1054.     switch(wall) {
  1055.           case W_NORTH:
  1056.         dy = 0; dx = 1;
  1057.         xx = croom->lx;
  1058.         yy = croom->hy + 1;
  1059.         break;
  1060.           case W_SOUTH:
  1061.         dy = 0; dx = 1;
  1062.         xx = croom->lx;
  1063.         yy = croom->ly - 1;
  1064.         break;
  1065.           case W_EAST:
  1066.         dy = 1; dx = 0;
  1067.         xx = croom->hx + 1;
  1068.         yy = croom->ly;
  1069.         break;
  1070.           case W_WEST:
  1071.         dy = 1; dx = 0;
  1072.         xx = croom->lx - 1;
  1073.         yy = croom->ly;
  1074.         break;
  1075.           default:
  1076.         dx = dy = xx = yy = 0;
  1077.         panic("search_door: Bad wall!");
  1078.         break;
  1079.     }
  1080.     while (xx <= croom->hx+1 && yy <= croom->hy+1) {
  1081.         if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
  1082.             *x = xx;
  1083.             *y = yy;
  1084.             if (cnt-- <= 0) 
  1085.                 return TRUE;
  1086.         }
  1087.         xx += dx;
  1088.         yy += dy;
  1089.     }
  1090.     return FALSE;
  1091. }
  1092.  
  1093. /* 
  1094.  * Dig a corridor between two points.
  1095.  */
  1096.  
  1097. boolean
  1098. dig_corridor(org,dest,nxcor,ftyp,btyp)
  1099. coord org, dest;
  1100. boolean nxcor;
  1101. schar ftyp, btyp;
  1102. {
  1103.     register int dx=0, dy=0, dix, diy, cct;
  1104.     register struct rm *crm;
  1105.     register int tx, ty, xx, yy;
  1106.  
  1107.     xx = org.x;  yy = org.y;
  1108.     tx = dest.x; ty = dest.y;
  1109.     if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 ||
  1110.         xx > COLNO-1 || tx > COLNO-1 ||
  1111.         yy > ROWNO-1 || ty > ROWNO-1) {
  1112. #ifdef DEBUG
  1113.         debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).",
  1114.                xx,yy,tx,ty);
  1115. #endif
  1116.         return FALSE;
  1117.     }
  1118.     if (tx > xx)        dx = 1;
  1119.     else if (ty > yy)    dy = 1;
  1120.     else if (tx < xx)    dx = -1;
  1121.     else            dy = -1;
  1122.     
  1123.     xx -= dx;
  1124.     yy -= dy;
  1125.     cct = 0;
  1126.     while(xx != tx || yy != ty) {
  1127.         /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
  1128.         if(cct++ > 500 || (nxcor && !rn2(35)))
  1129.         return FALSE;
  1130.  
  1131.         xx += dx;
  1132.         yy += dy;
  1133.  
  1134.         if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1)
  1135.         return FALSE;        /* impossible */
  1136.  
  1137.         crm = &levl[xx][yy];
  1138.         if(crm->typ == btyp) {
  1139.         if(ftyp != CORR || rn2(100)) {
  1140.             crm->typ = ftyp;
  1141.             if(nxcor && !rn2(50))
  1142.                 (void) mksobj_at(BOULDER, xx, yy, TRUE);
  1143.         } else {
  1144.             crm->typ = SCORR;
  1145.         }
  1146.         } else
  1147.         if(crm->typ != ftyp && crm->typ != SCORR) {
  1148.         /* strange ... */
  1149.         return FALSE;
  1150.         }
  1151.  
  1152.         /* find next corridor position */
  1153.         dix = abs(xx-tx);
  1154.         diy = abs(yy-ty);
  1155.  
  1156.         /* do we have to change direction ? */
  1157.         if(dy && dix > diy) {
  1158.         register int ddx = (xx > tx) ? -1 : 1;
  1159.  
  1160.         crm = &levl[xx+ddx][yy];
  1161.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  1162.             dx = ddx;
  1163.             dy = 0;
  1164.             continue;
  1165.         }
  1166.         } else if(dx && diy > dix) {
  1167.         register int ddy = (yy > ty) ? -1 : 1;
  1168.  
  1169.         crm = &levl[xx][yy+ddy];
  1170.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  1171.             dy = ddy;
  1172.             dx = 0;
  1173.             continue;
  1174.         }
  1175.         }
  1176.  
  1177.         /* continue straight on? */
  1178.         crm = &levl[xx+dx][yy+dy];
  1179.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  1180.         continue;
  1181.  
  1182.         /* no, what must we do now?? */
  1183.         if(dx) {
  1184.         dx = 0;
  1185.         dy = (ty < yy) ? -1 : 1;
  1186.         } else {
  1187.         dy = 0;
  1188.         dx = (tx < xx) ? -1 : 1;
  1189.         }
  1190.         crm = &levl[xx+dx][yy+dy];
  1191.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  1192.         continue;
  1193.         dy = -dy;
  1194.         dx = -dx;
  1195.     }
  1196.     return TRUE;
  1197. }
  1198.  
  1199. /*
  1200.  * Disgusting hack: since special levels have their rooms filled before
  1201.  * sorting the rooms, we have to re-arrange the speed values upstairs_room
  1202.  * and dnstairs_room after the rooms have been sorted.  On normal levels,
  1203.  * stairs don't get created until _after_ sorting takes place.
  1204.  */
  1205. static void
  1206. fix_stair_rooms()
  1207. {
  1208.     register i;
  1209.     register struct mkroom     *croom;
  1210.  
  1211.     if(xdnstair &&
  1212.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) &&
  1213.      (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) {
  1214.     for(i=0; i < nroom; i++) {
  1215.         croom = &rooms[i];
  1216.         if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&
  1217.            (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
  1218.         dnstairs_room = croom;
  1219.         break;
  1220.         }
  1221.     }
  1222.     if(i == nroom)
  1223.         panic("Couldn't find dnstair room in fix_stair_rooms!");
  1224.     }
  1225.     if(xupstair &&
  1226.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) &&
  1227.      (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) {
  1228.     for(i=0; i < nroom; i++) {
  1229.         croom = &rooms[i];
  1230.         if((croom->lx <= xupstair && xupstair <= croom->hx) &&
  1231.            (croom->ly <= yupstair && yupstair <= croom->hy)) {
  1232.         upstairs_room = croom;
  1233.         break;
  1234.         }
  1235.     }
  1236.     if(i == nroom)
  1237.         panic("Couldn't find upstair room in fix_stair_rooms!");
  1238.     }
  1239. }
  1240.  
  1241. /* 
  1242.  * Corridors always start from a door. But it can end anywhere...
  1243.  * Basically we search for door coordinates or for endpoints coordinates
  1244.  * (from a distance).
  1245.  */
  1246.  
  1247. static void
  1248. create_corridor(c)
  1249. corridor    *c;
  1250. {
  1251.     coord org, dest;
  1252.  
  1253.     if (c->src.room == -1) {
  1254.         sort_rooms();
  1255.         fix_stair_rooms();
  1256.         makecorridors();
  1257.         return;
  1258.     }
  1259.  
  1260.     if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
  1261.              c->src.door))
  1262.         return;
  1263.  
  1264.     if (c->dest.room != -1) {
  1265.         if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y,
  1266.                 c->dest.wall, c->dest.door))
  1267.             return;
  1268.         switch(c->src.wall) {
  1269.               case W_NORTH: org.y--; break;
  1270.               case W_SOUTH: org.y++; break;
  1271.               case W_WEST:  org.x--; break;
  1272.               case W_EAST:  org.x++; break;
  1273.         }
  1274.         switch(c->dest.wall) {
  1275.               case W_NORTH: dest.y--; break;
  1276.               case W_SOUTH: dest.y++; break;
  1277.               case W_WEST:  dest.x--; break;
  1278.               case W_EAST:  dest.x++; break;
  1279.         }
  1280.         (void) dig_corridor(org, dest, FALSE, CORR, STONE);
  1281.     }
  1282. }
  1283.  
  1284.  
  1285. /* 
  1286.  * Fill a room (shop, zoo, etc...) with appropriate stuff.
  1287.  */
  1288.  
  1289. void
  1290. fill_room(croom, prefilled)
  1291. struct mkroom     *croom;
  1292. boolean prefilled;
  1293. {
  1294.     if (!croom || croom->rtype == OROOM)
  1295.         return;
  1296.  
  1297.     if(prefilled) {
  1298.         switch(croom->rtype) {
  1299.         case COURT:
  1300.         level.flags.has_court = 1;
  1301.         break;
  1302. #ifdef ARMY
  1303.         case BARRACKS:
  1304.         level.flags.has_barracks = 1;
  1305.         break;
  1306. #endif
  1307.         case ZOO:
  1308.         level.flags.has_zoo = 1;
  1309.         break;
  1310.         case MORGUE:
  1311.         level.flags.has_morgue = 1;
  1312.         break;
  1313.         case SWAMP:
  1314.         level.flags.has_swamp = 1;
  1315.         break;
  1316.         case BEEHIVE:
  1317.         level.flags.has_beehive = 1;
  1318.         break;
  1319.         }
  1320.         return;
  1321.     }
  1322.     /* Vault ? */
  1323.     if (croom->rtype == VAULT) {
  1324.         int x,y;
  1325.         for (x=croom->lx;x<=croom->hx;x++)
  1326.             for (y=croom->ly;y<=croom->hy;y++)
  1327.             mkgold((long)rn1(depth(&u.uz)*100, 51), x, y);
  1328.         return;
  1329.     }
  1330.  
  1331.     /* Shop ? */
  1332.     if (croom->rtype >= SHOPBASE) {
  1333.         stock_room(croom->rtype - SHOPBASE, croom);
  1334.         return;
  1335.     }
  1336.  
  1337.     /* Zoo ? */
  1338.     switch (croom->rtype) {
  1339.           case COURT:
  1340.           case ZOO:
  1341.           case BEEHIVE:
  1342.           case MORGUE:
  1343.           case BARRACKS:
  1344.         fill_zoo(croom);
  1345.         break;
  1346.     }
  1347. }
  1348.  
  1349. static void
  1350. free_rooms(ro, n)
  1351. room **ro;
  1352. int n;
  1353. {
  1354.     short j;
  1355.     room *r;
  1356.     
  1357.     while(n--) {
  1358.         r = ro[n];
  1359.         Free(r->name);
  1360.         Free(r->parent);
  1361.         if (j = r->ndoor) {
  1362.             while(j--)
  1363.                 Free(r->doors[j]);
  1364.             Free(r->doors);
  1365.         }
  1366.         if (j = r->ntrap) {
  1367.             while (j--)
  1368.                 Free(r->traps[j]);
  1369.             Free(r->traps);
  1370.         }
  1371.         if (j = r->nmonster) {
  1372.             while (j--) {
  1373.                 Free(r->monsters[j]->name);
  1374.                 Free(r->monsters[j]->appear_as);
  1375.                 Free(r->monsters[j]);
  1376.             }
  1377.             Free(r->monsters);
  1378.         }
  1379.         if (j = r->nobject) {
  1380.             while(j--) {
  1381.                 Free(r->objects[j]->name);
  1382.                 Free(r->objects[j]);
  1383.             }
  1384.             Free(r->objects);
  1385.         }
  1386.         if (j = r->nstair) {
  1387.             while(j--)
  1388.                 Free(r->stairs[j]);
  1389.             Free(r->stairs);
  1390.         }
  1391.         if (j = r->naltar) {
  1392.             while (j--)
  1393.                 Free(r->altars[j]);
  1394.             Free(r->altars);
  1395.         }
  1396.         if (j = r->ngold) {
  1397.             while(j--)
  1398.                 Free(r->golds[j]);
  1399.             Free(r->golds);
  1400.         }
  1401.         if (j = r->nengraving) {
  1402.             while(j--) {
  1403.                 Free(r->engravings[j]->e.text);
  1404.                 Free(r->engravings[j]);
  1405.             }
  1406.             Free(r->engravings);
  1407.         }
  1408.         if (j = r->nfountain) {
  1409.             while(j--)
  1410.                 Free(r->fountains[j]);
  1411.             Free(r->fountains);
  1412.         }
  1413.         if (j = r->nsink) {
  1414.             while(j--)
  1415.                 Free(r->sinks[j]);
  1416.             Free(r->sinks);
  1417.         }
  1418.         if (j = r->npool) {
  1419.             while(j--)
  1420.                 Free(r->pools[j]);
  1421.             Free(r->pools);
  1422.         }
  1423.         Free(r);
  1424.     }
  1425. }
  1426.  
  1427. static void
  1428. build_room(r, pr)
  1429. room *r, *pr;
  1430. {
  1431.     boolean okroom;
  1432.     struct mkroom    *aroom;
  1433.     short i;
  1434.     xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
  1435.  
  1436.     if(pr) {
  1437.         aroom = &subrooms[nsubroom];
  1438.         okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
  1439.                     rtype, r->rlit);
  1440.     } else {
  1441.         aroom = &rooms[nroom];
  1442.         okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
  1443.                      r->yalign, rtype, r->rlit);
  1444.         r->mkr = aroom;
  1445.     }
  1446.  
  1447.     if (okroom) {
  1448.         /* Create subrooms if necessary... */
  1449.         for(i=0; i < r->nsubroom; i++)
  1450.             build_room(r->subrooms[i], r);
  1451.         /* And now we can fill the room! */
  1452.         
  1453.         /* Priority to the stairs */
  1454.  
  1455.         for(i=0; i <r->nstair; i++)
  1456.             create_stairs(r->stairs[i], aroom);
  1457.  
  1458.         /* Then to the various elements (sinks, etc..) */
  1459.         for(i = 0; i<r->nsink; i++)
  1460.             create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
  1461.         for(i = 0; i<r->npool; i++)
  1462.             create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
  1463.         for(i = 0; i<r->nfountain; i++)
  1464.             create_feature(r->fountains[i]->x, r->fountains[i]->y,
  1465.                    aroom, FOUNTAIN);
  1466.         for(i = 0; i<r->naltar; i++)
  1467.             create_altar(r->altars[i], aroom);
  1468.         for(i = 0; i<r->ndoor; i++)
  1469.             create_door(r->doors[i], aroom);
  1470.  
  1471.         /* The traps */
  1472.         for(i = 0; i<r->ntrap; i++)
  1473.             create_trap(r->traps[i], aroom);
  1474.  
  1475.         /* The monsters */
  1476.         for(i = 0; i<r->nmonster; i++)
  1477.             create_monster(r->monsters[i], aroom);
  1478.  
  1479.         /* The objects */
  1480.         for(i = 0; i<r->nobject; i++)
  1481.             create_object(r->objects[i], aroom);
  1482.  
  1483.         /* The gold piles */
  1484.         for(i = 0; i<r->ngold; i++)
  1485.             create_gold(r->golds[i], aroom);
  1486.  
  1487.         /* The engravings */
  1488.         for(i = 0; i<r->nengraving; i++) {
  1489.             schar xx, yy;
  1490.  
  1491.             xx = r->engravings[i]->x;
  1492.             yy = r->engravings[i]->y;
  1493.             get_room_loc(&xx, &yy, aroom);
  1494.             make_engr_at(xx, yy, r->engravings[i]->e.text,
  1495.                      0L, r->engravings[i]->etype);
  1496.         }
  1497. #ifdef SPECIALIZATION
  1498.         topologize(aroom,FALSE);        /* set roomno */
  1499. #else
  1500.         topologize(aroom);            /* set roomno */
  1501. #endif
  1502.         /* MRS - 07/04/91 - This is temporary but should result
  1503.          * in proper filling of shops, etc.
  1504.          * DLC - this can fail if corridors are added to this room
  1505.          * at a later point.  Currently no good way to fix this.
  1506.          */
  1507.         if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
  1508.     }
  1509. }
  1510.  
  1511. /*
  1512.  * set lighting in a region that will not become a room.
  1513.  */
  1514. static void
  1515. light_region(tmpregion)
  1516.     region  *tmpregion;
  1517. {
  1518.     register boolean litstate = tmpregion->rlit ? 1 : 0;
  1519.     register int hiy = tmpregion->y2;
  1520.     register int x, y;
  1521.     register struct rm *lev;
  1522.     int lowy = tmpregion->y1;
  1523.     int lowx = tmpregion->x1, hix = tmpregion->x2;
  1524.  
  1525.     if(litstate) {
  1526.     /* adjust region size for walls, but only if lighted */
  1527.     lowx = max(lowx-1,1);
  1528.     hix = min(hix+1,COLNO-1);
  1529.     lowy = max(lowy-1,0);
  1530.     hiy = min(hiy+1, ROWNO-1);
  1531.     }
  1532.     for(x = lowx; x <= hix; x++) {
  1533.     lev = &levl[x][lowy];
  1534.     for(y = lowy; y <= hiy; y++)
  1535.         lev++->lit = litstate;
  1536.     }
  1537. }
  1538.  
  1539. /* initialization common to all special levels */
  1540. static void
  1541. load_common_data(fd, typ)
  1542. FILE *fd;
  1543. int typ;
  1544. {
  1545.     uchar    n;
  1546.     long    lev_flags;
  1547.     int    i;
  1548.  
  1549.       {
  1550.     aligntyp atmp;
  1551.     /* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
  1552.     i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
  1553.     if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
  1554.       }
  1555.  
  1556.     level.flags.is_maze_lev = typ == SP_LEV_MAZE;
  1557.  
  1558.     /* free up old level regions */
  1559.     if(num_lregions) {
  1560.         for(i=0; i<num_lregions; i++)
  1561.             if(lregions[i].rname) Free(lregions[i].rname);
  1562.         Free(lregions);
  1563.         num_lregions = 0;
  1564.     }
  1565.     lregions = (lev_region *) 0;
  1566.  
  1567.     /* Read the level initialization data */
  1568.     Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
  1569.     if(init_lev.init_present) {
  1570.         if(init_lev.lit < 0)
  1571.         init_lev.lit = rn2(2);
  1572.         mkmap(&init_lev);
  1573.     }
  1574.  
  1575.     /* Read the per level flags */
  1576.     Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
  1577.     if (lev_flags & NOTELEPORT)
  1578.         level.flags.noteleport = 1;
  1579.     if (lev_flags & HARDFLOOR)
  1580.         level.flags.hardfloor = 1;
  1581.     if (lev_flags & NOMMAP)
  1582.         level.flags.nommap = 1;
  1583.     if (lev_flags & SHORTSIGHTED)
  1584.         level.flags.shortsighted = 1;
  1585.  
  1586.     /* Read message */
  1587.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  1588.     if (n) {
  1589.         lev_message = (char *) alloc(n + 1);
  1590.         Fread((genericptr_t) lev_message, 1, (int) n, fd);
  1591.         lev_message[n] = 0;
  1592.     }
  1593. }
  1594.  
  1595. static boolean
  1596. load_rooms(fd)
  1597. FILE *fd;
  1598. {
  1599.     xchar        nrooms;
  1600.     char        n;
  1601.     short        size;
  1602.     corridor    tmpcor;
  1603.     room**        tmproom;
  1604.     int        i, j, ncorr;
  1605.  
  1606.     load_common_data(fd, SP_LEV_ROOMS);
  1607.  
  1608.     Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
  1609.     if (n) {
  1610.         Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
  1611.         sp_lev_shuffle(robjects, (char *)0, (int)n);
  1612.     }
  1613.  
  1614.     Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
  1615.     if (n) {
  1616.         Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
  1617.         sp_lev_shuffle(rmonst, (char *)0, (int)n);
  1618.     }
  1619.  
  1620.     Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
  1621.                         /* Number of rooms to read */
  1622.     tmproom = NewTab(room,nrooms);
  1623.     for (i=0;i<nrooms;i++) {
  1624.         room *r;
  1625.  
  1626.         r = tmproom[i] = New(room);
  1627.  
  1628.         /* Let's see if this room has a name */
  1629.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1630.         if (size > 0) {    /* Yup, it does! */
  1631.             r->name = (char *) alloc(size + 1);
  1632.             Fread((genericptr_t) r->name, 1, size, fd);
  1633.             r->name[size] = 0;
  1634.         } else
  1635.             r->name = (char *) 0;
  1636.  
  1637.         /* Let's see if this room has a parent */
  1638.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1639.         if (size > 0) {    /* Yup, it does! */
  1640.             r->parent = (char *) alloc(size + 1);
  1641.             Fread((genericptr_t) r->parent, 1, size, fd);
  1642.             r->parent[size] = 0;
  1643.         } else
  1644.             r->parent = (char *) 0;
  1645.         
  1646.         Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
  1647.                     /* x pos on the grid (1-5) */
  1648.         Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
  1649.                      /* y pos on the grid (1-5) */
  1650.         Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
  1651.                      /* width of the room */
  1652.         Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
  1653.                      /* height of the room */
  1654.         Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
  1655.                      /* horizontal alignment */
  1656.         Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
  1657.                      /* vertical alignment */
  1658.         Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
  1659.                      /* type of room (zoo, shop, etc.) */
  1660.         Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
  1661.                      /* chance of room being special. */
  1662.         Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
  1663.                      /* lit or not ? */
  1664.         Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
  1665.                      /* to be filled? */
  1666.         r->nsubroom= 0;
  1667.  
  1668.         /* read the doors */
  1669.         Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
  1670.         if(n = r->ndoor)
  1671.             r->doors = NewTab(room_door, n);
  1672.         while(n--) {
  1673.             r->doors[n] = New(room_door);
  1674.             Fread((genericptr_t) r->doors[n], 1,
  1675.                 sizeof(room_door), fd);
  1676.         }
  1677.  
  1678.         /* read the traps */
  1679.         Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
  1680.         if(n = r->ntrap)
  1681.             r->traps = NewTab(trap, n);
  1682.         while(n--) {
  1683.             r->traps[n] = New(trap);
  1684.             Fread((genericptr_t) r->traps[n], 1, sizeof(trap), fd);
  1685.         }
  1686.  
  1687.         /* read the monsters */
  1688.         Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
  1689.         if(n = r->nmonster)
  1690.             r->monsters = NewTab(monster, n);
  1691.         while(n--) {
  1692.             r->monsters[n] = New(monster);
  1693.             Fread((genericptr_t) r->monsters[n], 1,
  1694.                 sizeof(monster), fd);
  1695.             Fread((genericptr_t) &size, sizeof(size), 1, fd);
  1696.             if (size) {
  1697.                 r->monsters[n]->name= (char *) alloc(size + 1);
  1698.                 Fread((genericptr_t)r->monsters[n]->name,
  1699.                     1, size, fd);
  1700.                 r->monsters[n]->name[size] = 0;
  1701.             } else
  1702.                 r->monsters[n]->name = (char *) 0;
  1703.  
  1704.             Fread((genericptr_t) &size, sizeof(size), 1, fd);
  1705.             if (size) {
  1706.                 r->monsters[n]->appear_as=
  1707.                             (char *) alloc(size + 1);
  1708.                 Fread((genericptr_t)r->monsters[n]->appear_as,
  1709.                     1, size, fd);
  1710.                 r->monsters[n]->appear_as[size] = 0;
  1711.             } else
  1712.                 r->monsters[n]->appear_as = (char *) 0;
  1713.          }
  1714.  
  1715.         /* read the objects */
  1716.         Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
  1717.         if(n = r->nobject)
  1718.             r->objects = NewTab(object, n);
  1719.         while (n--) {
  1720.             r->objects[n] = New(object);
  1721.             Fread((genericptr_t) r->objects[n], 1,
  1722.                 sizeof(object), fd);
  1723.             Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1724.             if (size) {
  1725.                 r->objects[n]->name = (char *) alloc(size + 1);
  1726.                 Fread((genericptr_t)r->objects[n]->name,
  1727.                     1, size, fd);
  1728.                 r->objects[n]->name[size] = 0;
  1729.             } else
  1730.                 r->objects[n]->name = (char *) 0;
  1731.         }
  1732.  
  1733.         /* read the stairs */
  1734.         Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
  1735.         if (n = r->nstair)
  1736.             r->stairs = NewTab(stair, n);
  1737.         while (n--) {
  1738.             r->stairs[n] = New(stair);
  1739.             Fread((genericptr_t) r->stairs[n], 1,
  1740.                 sizeof(stair), fd);
  1741.         }
  1742.  
  1743.         /* read the altars */
  1744.         Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
  1745.         if (n = r->naltar)
  1746.             r->altars = NewTab(altar, n);
  1747.         while (n--) {
  1748.             r->altars[n] = New(altar);
  1749.             Fread((genericptr_t) r->altars[n], 1,
  1750.                 sizeof(altar), fd);
  1751.         }
  1752.  
  1753.         /* read the gold piles */
  1754.         Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
  1755.         if (n = r->ngold)
  1756.             r->golds = NewTab(gold, n);
  1757.         while (n--) {
  1758.             r->golds[n] = New(gold);
  1759.             Fread((genericptr_t) r->golds[n], 1, sizeof(gold), fd);
  1760.         }
  1761.  
  1762.         /* read the engravings */
  1763.         Fread((genericptr_t) &r->nengraving, 1,
  1764.             sizeof(r->nengraving), fd);
  1765.         if (n = r->nengraving)
  1766.             r->engravings = NewTab(engraving,n);
  1767.         while(n--) {
  1768.             r->engravings[n] = New(engraving);
  1769.             Fread((genericptr_t) r->engravings[n],
  1770.                 1, sizeof *r->engravings[n], fd);
  1771.             size = r->engravings[n]->e.length;
  1772.             r->engravings[n]->e.text = (char *) alloc(size+1);
  1773.             Fread((genericptr_t) r->engravings[n]->e.text,
  1774.                 1, size, fd);
  1775.             r->engravings[n]->e.text[size] = '\0';
  1776.         }
  1777.  
  1778.         /* read the fountains */
  1779.         Fread((genericptr_t) &r->nfountain, 1,
  1780.             sizeof(r->nfountain), fd);
  1781.         if (n = r->nfountain)
  1782.             r->fountains = NewTab(fountain, n);
  1783.         while (n--) {
  1784.             r->fountains[n] = New(fountain);
  1785.             Fread((genericptr_t) r->fountains[n], 1,
  1786.                 sizeof(fountain), fd);
  1787.         }
  1788.  
  1789.         /* read the sinks */
  1790.         Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
  1791.         if (n = r->nsink)
  1792.             r->sinks = NewTab(sink, n);
  1793.         while (n--) {
  1794.             r->sinks[n] = New(sink);
  1795.             Fread((genericptr_t) r->sinks[n], 1, sizeof(sink), fd);
  1796.         }
  1797.  
  1798.         /* read the pools */
  1799.         Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
  1800.         if (n = r->npool)
  1801.             r->pools = NewTab(pool,n);
  1802.         while (n--) {
  1803.             r->pools[n] = New(pool);
  1804.             Fread((genericptr_t) r->pools[n], 1, sizeof(pool), fd);
  1805.         }
  1806.  
  1807.     }
  1808.  
  1809.     /* Now that we have loaded all the rooms, search the
  1810.      * subrooms and create the links.
  1811.      */
  1812.  
  1813.     for (i = 0; i<nrooms; i++)
  1814.         if (tmproom[i]->parent) {
  1815.             /* Search the parent room */
  1816.             for(j=0; j<nrooms; j++)
  1817.             if (tmproom[j]->name && !strcmp(tmproom[j]->name,
  1818.                                tmproom[i]->parent)) {
  1819.                 n = tmproom[j]->nsubroom++;
  1820.                 tmproom[j]->subrooms[n] = tmproom[i];
  1821.                 break;
  1822.             }
  1823.         }
  1824.  
  1825.     /* 
  1826.      * Create the rooms now...
  1827.      */
  1828.  
  1829.     for (i=0; i < nrooms; i++)
  1830.         if(!tmproom[i]->parent)
  1831.         build_room(tmproom[i], (room *) 0);
  1832.  
  1833.     free_rooms(tmproom, nrooms);
  1834.  
  1835.     /* read the corridors */
  1836.  
  1837.     Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
  1838.     for (i=0; i<ncorr; i++) {
  1839.         Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
  1840.         create_corridor(&tmpcor);
  1841.     }
  1842.  
  1843.     return TRUE;
  1844. }
  1845.  
  1846. /*
  1847.  * Select a random coordinate in the maze.
  1848.  *
  1849.  * We want a place not 'touched' by the loader.  That is, a place in
  1850.  * the maze outside every part of the special level.
  1851.  */
  1852.  
  1853. static void
  1854. maze1xy(m)
  1855. coord *m;
  1856. {
  1857.     do {
  1858.         m->x = rn1(x_maze_max - 3, 3);
  1859.         m->y = rn1(y_maze_max - 3, 3);
  1860.     } while (!(m->x % 2) || !(m->y % 2) || Map[m->x][m->y]);
  1861. }
  1862.  
  1863. /* 
  1864.  * The Big Thing: special maze loader
  1865.  *
  1866.  * Could be cleaner, but it works.
  1867.  */
  1868.  
  1869. static boolean
  1870. load_maze(fd)
  1871. FILE *fd;
  1872. {
  1873.     xchar   x, y, typ;
  1874.     boolean prefilled;
  1875.  
  1876.     char    n, numpart = 0;
  1877.     xchar   nwalk = 0, nwalk_sav;
  1878.     short   filling;
  1879.     char    halign, valign;
  1880.  
  1881.     int     xi, yi, dir;
  1882.     coord   mm;
  1883.     int     mapcount, mapcountmax, mapfact;
  1884.  
  1885.     lev_region  tmplregion;
  1886.     region  tmpregion;
  1887.     door    tmpdoor;
  1888.     trap    tmptrap;
  1889.     monster tmpmons;
  1890.     object  tmpobj;
  1891.     drawbridge tmpdb;
  1892.     walk    tmpwalk;
  1893.     digpos  tmpdig;
  1894.     lad     tmplad;
  1895.     stair   tmpstair, prevstair;
  1896.     altar   tmpaltar;
  1897.     gold    tmpgold;
  1898.     fountain tmpfountain;
  1899.     engraving tmpengraving;
  1900.     xchar   mustfill[(MAXNROFROOMS+1)*2];
  1901.     struct trap *badtrap;
  1902.     boolean has_bounds;
  1903.  
  1904.     load_common_data(fd, SP_LEV_MAZE);
  1905.  
  1906.     /* Initialize map */
  1907.     Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
  1908.     if(!init_lev.init_present) /* don't init if mkmap() has been called */
  1909.       for(x = 2; x <= x_maze_max; x++)
  1910.     for(y = 0; y <= y_maze_max; y++)
  1911.         if (filling == -1) {
  1912. #ifndef WALLIFIED_MAZE
  1913.             levl[x][y].typ = STONE;
  1914. #else
  1915.             levl[x][y].typ =
  1916.             (y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
  1917. #endif
  1918.             Map[x][y] = 0;
  1919.         } else {
  1920.             levl[x][y].typ = filling;
  1921.             Map[x][y] = 0;
  1922.         }
  1923.  
  1924.     /* Start reading the file */
  1925.     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
  1926.                         /* Number of parts */
  1927.     if (!numpart || numpart > 9)
  1928.     panic("load_maze error: numpart = %d", (int) numpart);
  1929.  
  1930.     while (numpart--) {
  1931.     Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
  1932.                     /* Horizontal alignment */
  1933.     Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
  1934.                     /* Vertical alignment */
  1935.     Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
  1936.                     /* size in X */
  1937.     Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
  1938.                     /* size in Y */
  1939.     switch((int) halign) {
  1940.         case LEFT:        xstart = 3;                 break;
  1941.         case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);    break;
  1942.         case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);    break;
  1943.         case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);    break;
  1944.         case RIGHT:     xstart = x_maze_max-xsize-1;        break;
  1945.     }
  1946.     switch((int) valign) {
  1947.         case TOP:        ystart = 3;                 break;
  1948.         case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);    break;
  1949.         case BOTTOM:    ystart = y_maze_max-ysize-1;        break;
  1950.     }
  1951.     if (!(xstart % 2)) xstart++;
  1952.     if (!(ystart % 2)) ystart++;
  1953.     if ((ystart < 0) || (ystart + ysize > ROWNO)) {
  1954.         /* try to move the start a bit */
  1955.         ystart += (ystart > 0) ? -2 : 2;
  1956.         if(ysize == ROWNO) ystart = 0;
  1957.         if(ystart < 0 || ystart + ysize > ROWNO)
  1958.         panic("reading special level with ysize to large");
  1959.     }
  1960.  
  1961.     /*
  1962.      * If any CROSSWALLs are found, must change to ROOM after REGION's
  1963.      * are laid out.  CROSSWALLS are used to specify "invisible"
  1964.      * boundaries where DOOR syms look bad or aren't desirable.
  1965.      */
  1966.     has_bounds = FALSE;
  1967.  
  1968.     if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
  1969.         xstart = 1;
  1970.         ystart = 0;
  1971.         xsize = COLNO-1;
  1972.         ysize = ROWNO;
  1973.     } else {
  1974.         /* Load the map */
  1975.         for(y = ystart; y < ystart+ysize; y++)
  1976.         for(x = xstart; x < xstart+xsize; x++) {
  1977.             levl[x][y].typ = (schar) fgetc(fd);
  1978.             levl[x][y].lit = FALSE;
  1979.             /*
  1980.              * Note: Even though levl[x][y].typ is type schar,
  1981.              *     lev_comp.y saves it as type char. Since schar != char
  1982.              *     all the time we must make this exception or hack
  1983.              *     through lev_comp.y to fix.
  1984.              */
  1985.  
  1986.             /*
  1987.              *  Set secret doors to closed (why not trapped too?).  Set
  1988.              *  the horizontal bit.
  1989.              */
  1990.             if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
  1991.             if(levl[x][y].typ == SDOOR)
  1992.                 levl[x][y].doormask = D_CLOSED;
  1993.             /*
  1994.              *  If there is a wall to the left that connects to a
  1995.              *  (secret) door, then it is horizontal.  This does
  1996.              *  not allow (secret) doors to be corners of rooms.
  1997.              */
  1998.             if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
  1999.                         levl[x-1][y].horizontal))
  2000.                 levl[x][y].horizontal = 1;
  2001.             } else if(levl[x][y].typ == HWALL)
  2002.             levl[x][y].horizontal = 1;
  2003.             else if(levl[x][y].typ == LAVAPOOL)
  2004.             levl[x][y].lit = 1;
  2005.             else if(levl[x][y].typ == CROSSWALL)
  2006.             has_bounds = TRUE;
  2007.             Map[x][y] = 1;
  2008.         }
  2009.     }
  2010.  
  2011.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2012.                         /* Number of level regions */
  2013.     if(n) {
  2014.         if(num_lregions) {
  2015.         /* realloc the lregion space to add the new ones */
  2016.         /* don't really free it up until the whole level is done */
  2017.         lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
  2018.                             (n+num_lregions));
  2019.         (void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
  2020.                     sizeof(lev_region) * num_lregions);
  2021.         Free(lregions);
  2022.         num_lregions += n;
  2023.         lregions = newl;
  2024.         } else {
  2025.         num_lregions = n;
  2026.         lregions = (lev_region *) alloc(sizeof(lev_region) * n);
  2027.         }
  2028.     }
  2029.  
  2030.     while(n--) {
  2031.         Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
  2032.         if(tmplregion.rname) {
  2033.         char len;
  2034.  
  2035.         Fread((genericptr_t) &len, sizeof(len), 1, fd);
  2036.         tmplregion.rname = (char *) alloc(len + 1);
  2037.         Fread((genericptr_t) tmplregion.rname, len, 1, fd);
  2038.         tmplregion.rname[len] = 0;
  2039.         }
  2040.         if(!tmplregion.in_islev) {
  2041.         get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
  2042.                                 DRY|WET);
  2043.         get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
  2044.                                 DRY|WET);
  2045.         }
  2046.         if(!tmplregion.del_islev) {
  2047.         get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
  2048.                                 DRY|WET);
  2049.         get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
  2050.                                 DRY|WET);
  2051.         }
  2052.         lregions[n] = tmplregion;
  2053.     }
  2054.  
  2055.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2056.                         /* Random objects */
  2057.     if(n) {
  2058.         Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
  2059.         sp_lev_shuffle(robjects, (char *)0, (int)n);
  2060.     }
  2061.  
  2062.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2063.                         /* Random locations */
  2064.     if(n) {
  2065.         Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
  2066.         Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
  2067.         sp_lev_shuffle(rloc_x, rloc_y, (int)n);
  2068.     }
  2069.  
  2070.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2071.                         /* Random monsters */
  2072.     if(n) {
  2073.         Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
  2074.         sp_lev_shuffle(rmonst, (char *)0, (int)n);
  2075.     }
  2076.  
  2077.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2078.                         /* Number of subrooms */
  2079.  
  2080.     (void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
  2081.  
  2082.     while(n--) {
  2083.         register struct mkroom *troom;
  2084.  
  2085.         Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
  2086.  
  2087.         if(tmpregion.rtype > MAXRTYPE) {
  2088.             tmpregion.rtype -= MAXRTYPE+1;
  2089.             prefilled = TRUE;
  2090.         } else
  2091.             prefilled = FALSE;
  2092.  
  2093.         if(tmpregion.rlit < 0)
  2094.             tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
  2095.             ? TRUE : FALSE;
  2096.  
  2097.         get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
  2098.         get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
  2099.  
  2100.         if (((tmpregion.rtype == OROOM) && !tmpregion.rirreg) ||
  2101.             (nroom >= MAXNROFROOMS)) {
  2102.             if(tmpregion.rtype != OROOM || tmpregion.rirreg)
  2103.             impossible("Too many rooms on new level!");
  2104.             light_region(&tmpregion);
  2105.             continue;
  2106.         }
  2107.  
  2108.         troom = &rooms[nroom];
  2109.  
  2110.         /* mark rooms that must be filled, but do it later */
  2111.         if (tmpregion.rtype != OROOM)
  2112.             mustfill[nroom] = (prefilled ? 2 : 1);
  2113.  
  2114.         if(tmpregion.rirreg) {
  2115.             min_rx = max_rx = tmpregion.x1;
  2116.             min_ry = max_ry = tmpregion.y1;
  2117.             flood_fill_rm(tmpregion.x1, tmpregion.y1,
  2118.                   nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
  2119.             add_room(min_rx, min_ry, max_rx, max_ry,
  2120.                  FALSE, tmpregion.rtype, TRUE);
  2121.             troom->rlit = tmpregion.rlit;
  2122.             troom->irregular = TRUE;
  2123.         } else {
  2124.             add_room(tmpregion.x1, tmpregion.y1,
  2125.                  tmpregion.x2, tmpregion.y2,
  2126.                  tmpregion.rlit, tmpregion.rtype, TRUE);
  2127. #ifdef SPECIALIZATION
  2128.             topologize(troom,FALSE);        /* set roomno */
  2129. #else
  2130.             topologize(troom);            /* set roomno */
  2131. #endif
  2132.         }
  2133.     }
  2134.  
  2135.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2136.                         /* Number of doors */
  2137.     while(n--) {
  2138.         struct mkroom *croom = &rooms[0];
  2139.  
  2140.         Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
  2141.  
  2142.         x = tmpdoor.x;    y = tmpdoor.y;
  2143.         typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
  2144.  
  2145.         get_location(&x, &y, DRY);
  2146.         if(levl[x][y].typ != SDOOR)
  2147.             levl[x][y].typ = DOOR;
  2148.         else {
  2149.             if(typ < D_CLOSED)
  2150.                 typ = D_CLOSED; /* force it to be closed */
  2151.         }
  2152.         levl[x][y].doormask = typ;
  2153.  
  2154.         /* Now the complicated part, list it with each subroom */
  2155.         /* The dog move and mail daemon routines use this */
  2156.         while(croom->hx >= 0 && doorindex < DOORMAX) {
  2157.             if(croom->hx >= x-1 && croom->lx <= x+1 &&
  2158.                croom->hy >= y-1 && croom->ly <= y+1) {
  2159.             /* Found it */
  2160.             add_door(x, y, croom);
  2161.             }
  2162.             croom++;
  2163.         }
  2164.     }
  2165.  
  2166.     /* now that we have rooms _and_ associated doors, fill the rooms */
  2167.     for(n = 0; n < SIZE(mustfill); n++)
  2168.         if(mustfill[n])
  2169.         fill_room(&rooms[n], (mustfill[n] == 2));
  2170.  
  2171.     /* if special boundary syms (CROSSWALL) in map, remove them now */
  2172.     if(has_bounds) {
  2173.         for(x = xstart; x < xstart+xsize; x++)
  2174.         for(y = ystart; y < ystart+ysize; y++)
  2175.             if(levl[x][y].typ == CROSSWALL)
  2176.             levl[x][y].typ = ROOM;
  2177.     }
  2178.  
  2179.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2180.                         /* Number of traps */
  2181.     while(n--) {
  2182.         Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
  2183.  
  2184.         create_trap(&tmptrap, (struct mkroom *)0);
  2185.     }
  2186.  
  2187.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2188.                         /* Number of monsters */
  2189.     while(n--) {
  2190.         short size;
  2191.  
  2192.         Fread((genericptr_t) &tmpmons, 1, sizeof(tmpmons), fd);
  2193.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2194.         if (size) {
  2195.             tmpmons.name = (char *) alloc(size + 1);
  2196.             Fread((genericptr_t) tmpmons.name, 1, size, fd);
  2197.             tmpmons.name[size] = 0;
  2198.         } else
  2199.             tmpmons.name = (char *) 0;
  2200.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2201.         if (size) {
  2202.             tmpmons.appear_as = (char *) alloc(size + 1);
  2203.             Fread((genericptr_t) tmpmons.appear_as, 1, size, fd);
  2204.             tmpmons.appear_as[size] = 0;
  2205.         } else
  2206.             tmpmons.appear_as = (char *) 0;
  2207.  
  2208.         create_monster(&tmpmons, (struct mkroom *)0);
  2209.  
  2210.         if (tmpmons.name)
  2211.             free((genericptr_t) tmpmons.name);
  2212.         if (tmpmons.appear_as)
  2213.             free((genericptr_t) tmpmons.appear_as);
  2214.     }
  2215.  
  2216.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2217.                         /* Number of objects */
  2218.     while(n--) {
  2219.         short size;
  2220.  
  2221.         Fread((genericptr_t) &tmpobj, 1, sizeof(object), fd);
  2222.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2223.         if (size) {
  2224.             tmpobj.name = (char *) alloc(size + 1);
  2225.             Fread((genericptr_t) tmpobj.name, 1, size, fd);
  2226.             tmpobj.name[size] = 0;
  2227.         } else
  2228.             tmpobj.name = (char *) 0;
  2229.  
  2230.         create_object(&tmpobj, (struct mkroom *)0);
  2231.  
  2232.         if (size)
  2233.             free((genericptr_t) tmpobj.name);
  2234.     }
  2235.  
  2236.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2237.                         /* Number of drawbridges */
  2238.     while(n--) {
  2239.         Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
  2240.  
  2241.         x = tmpdb.x;  y = tmpdb.y;
  2242.         get_location(&x, &y, DRY|WET);
  2243.  
  2244.         if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
  2245.             impossible("Cannot create drawbridge.");
  2246.     }
  2247.  
  2248.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2249.                         /* Number of mazewalks */
  2250.     while(n--) {
  2251.         Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
  2252.  
  2253.         get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
  2254.  
  2255.         walklist[nwalk++] = tmpwalk;
  2256.     }
  2257.  
  2258.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2259.                         /* Number of non_diggables */
  2260.     while(n--) {
  2261.         Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
  2262.  
  2263.         get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
  2264.         get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
  2265.  
  2266.         make_walls_nondiggable(tmpdig.x1, tmpdig.y1,
  2267.                        tmpdig.x2, tmpdig.y2);
  2268.     }
  2269.  
  2270.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2271.                         /* Number of ladders */
  2272.     while(n--) {
  2273.         Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
  2274.  
  2275.         x = tmplad.x;  y = tmplad.y;
  2276.         get_location(&x, &y, DRY);
  2277.  
  2278.         levl[x][y].typ = LADDER;
  2279.         if (tmplad.up == 1) {
  2280.             xupladder = x;    yupladder = y;
  2281.             levl[x][y].ladder = LA_UP;
  2282.         } else {
  2283.             xdnladder = x;    ydnladder = y;
  2284.             levl[x][y].ladder = LA_DOWN;
  2285.         }
  2286.     }
  2287.  
  2288.     prevstair.x = prevstair.y = 0;
  2289.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2290.                         /* Number of stairs */
  2291.     while(n--) {
  2292.         Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
  2293.  
  2294.         xi = 0;
  2295.         do {
  2296.             x = tmpstair.x;  y = tmpstair.y;
  2297.             get_location(&x, &y, DRY);
  2298.         } while(prevstair.x && xi++ < 100 &&
  2299.             distmin(x,y,prevstair.x,prevstair.y) <= 8);
  2300.         if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
  2301.         mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
  2302.         prevstair.x = x;
  2303.         prevstair.y = y;
  2304.     }
  2305.  
  2306.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2307.                         /* Number of altars */
  2308.     while(n--) {
  2309.         Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
  2310.  
  2311.         create_altar(&tmpaltar, (struct mkroom *)0);
  2312.     }
  2313.  
  2314.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2315.                         /* Number of gold pile */
  2316.     while (n--) {
  2317.         Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
  2318.  
  2319.         create_gold(&tmpgold, (struct mkroom *)0);
  2320.     }
  2321.  
  2322.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2323.                         /* Number of engravings */
  2324.     while(n--) {
  2325.         int size;
  2326.         Fread((genericptr_t) &tmpengraving, 1,
  2327.             sizeof(tmpengraving), fd);
  2328.         size = tmpengraving.e.length;
  2329.         tmpengraving.e.text = (char *) alloc(size+1);
  2330.         Fread((genericptr_t) tmpengraving.e.text, 1, size, fd);
  2331.         tmpengraving.e.text[size] = '\0';
  2332.         
  2333.         x = tmpengraving.x; y = tmpengraving.y;
  2334.         get_location(&x, &y, DRY);
  2335.         make_engr_at(x, y, tmpengraving.e.text, 0L, tmpengraving.etype);
  2336.         free((genericptr_t) tmpengraving.e.text);
  2337.     }
  2338.  
  2339.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2340.                         /* Number of fountains */
  2341.     while (n--) {
  2342.         Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
  2343.  
  2344.         create_feature(tmpfountain.x, tmpfountain.y,
  2345.                    (struct mkroom *)0, FOUNTAIN);
  2346.     }
  2347.     }
  2348.  
  2349.     nwalk_sav = nwalk;
  2350.     while(nwalk--) {
  2351.         xi = walklist[nwalk].x;
  2352.         yi = walklist[nwalk].y;
  2353.         dir = walklist[nwalk].dir;
  2354.  
  2355.         move(&xi, &yi, dir);
  2356.         x = xi;
  2357.         y = yi;
  2358.  
  2359.         if(!IS_DOOR(levl[x][y].typ)) {
  2360. #ifndef WALLIFIED_MAZE
  2361.         levl[x][y].typ = CORR;
  2362. #else
  2363.         levl[x][y].typ = ROOM;
  2364. #endif
  2365.         levl[x][y].flags = 0;
  2366.         }
  2367.  
  2368.         /*
  2369.          * We must be sure that the parity of the coordinates for
  2370.          * walkfrom() is odd.  But we must also take into account
  2371.          * what direction was chosen.
  2372.          */
  2373.         if(!(x % 2)) {
  2374.         if (dir == W_EAST)
  2375.             x++;
  2376.         else
  2377.             x--;
  2378.  
  2379.         /* no need for IS_DOOR check; out of map bounds */
  2380. #ifndef WALLIFIED_MAZE
  2381.         levl[x][y].typ = CORR;
  2382. #else
  2383.         levl[x][y].typ = ROOM;
  2384. #endif
  2385.         levl[x][y].flags = 0;
  2386.         }
  2387.  
  2388.         if (!(y % 2))
  2389.         if (dir == W_SOUTH)
  2390.             y++;
  2391.         else
  2392.             y--;
  2393.  
  2394.         walkfrom(x, y);
  2395.     }
  2396.     wallification(1, 0, COLNO-1, ROWNO-1);
  2397.  
  2398.     /*
  2399.      * If there's a significant portion of maze unused by the special level,
  2400.      * we don't want it empty.
  2401.      *
  2402.      * Makes the number of traps, monsters, etc. proportional
  2403.      * to the size of the maze.
  2404.      */
  2405.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
  2406.  
  2407.     for(x = 2; x < x_maze_max; x++)
  2408.     for(y = 0; y < y_maze_max; y++)
  2409.         if(Map[x][y]) mapcount--;
  2410.  
  2411.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
  2412.         mapfact = (int) ((mapcount * 100L) / mapcountmax);
  2413.         for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
  2414.             maze1xy(&mm);
  2415.             (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
  2416.                             mm.x, mm.y, TRUE);
  2417.         }
  2418.         for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
  2419.             maze1xy(&mm);
  2420.             (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE);
  2421.         }
  2422.         maze1xy(&mm);
  2423.         (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
  2424.         for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
  2425.             maze1xy(&mm);
  2426.             (void) makemon((struct permonst *) 0, mm.x, mm.y);
  2427.         }
  2428.         for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
  2429.             maze1xy(&mm);
  2430.             mkgold(0L,mm.x,mm.y);
  2431.         }
  2432.         for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
  2433.             int trytrap = rndtrap();
  2434.  
  2435.             maze1xy(&mm);
  2436.             if (is_pool(mm.x,mm.y)) continue;
  2437.             if (sobj_at(BOULDER, mm.x, mm.y))
  2438.             while ((trytrap == PIT) || (trytrap == SPIKED_PIT)) 
  2439.                 trytrap = rndtrap();
  2440.             (void) maketrap(mm.x, mm.y, trytrap);
  2441.         }
  2442.     }
  2443.     return TRUE;
  2444. }
  2445.  
  2446. /*
  2447.  * General loader
  2448.  */
  2449.  
  2450. boolean
  2451. load_special(name)
  2452. const char *name;
  2453. {
  2454.     FILE *fd;
  2455.     boolean result;
  2456.     char c;
  2457.  
  2458.     fd = fopen_datafile(name, RDMODE);
  2459.     if (!fd) return FALSE;
  2460.  
  2461.     Fread((genericptr_t) &c, 1, sizeof(c), fd); /* c Header */
  2462.  
  2463.     switch (c) {
  2464.         case SP_LEV_ROOMS:
  2465.             result = load_rooms(fd);
  2466.             break;
  2467.         case SP_LEV_MAZE:
  2468.             result = load_maze(fd);
  2469.             break;
  2470.         default:    /* ??? */
  2471.             result = FALSE;
  2472.     }
  2473.     (void)fclose(fd);
  2474.     return result;
  2475. }
  2476.  
  2477. /*sp_lev.c*/
  2478.